//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __AUDIOCARD_H__
#define __AUDIOCARD_H__

#include <elaaudio.h>

////////////////////////////////////////////////////////////////////////////////
//
// Compile flags
//
#define HEADSET_AUTOOPEN
#define MICBIAS_AUTOOPEN
#define AUDIO_INOUT_ATSAMETIME
//#define BLUETOOTH_PLAY_RECORD_ENABLE // Internal play & record testing
////////////////////////////////////////////////////////////////////////////////
//
// Debug information control
//
//#define DEBUG_AUDIO
#ifdef DEBUG_AUDIO

#define DBGOUT(m, x)  if ((m)) kprintf x
#define DBGOUT_FUNC(m, x) if ((m)) x
#define DBG_ERR     1
#define DBG_LOG     1
#define DBG_DUMP    1
#define DBG_ISR     0
#define DBG_BUF     0
#define DBG_LOOP    1
#define DBG_DUMP1   0
#define DBG_ACLINK  1
#define DBG_POWER   1
#define DBG_READ    0
#define DBG_WRITE   0
#undef assert
INLINE void _DrvAssert(const char *szExpr, const char *szFile, int nLine)
{
    cprintf("Assertion failed: %s, file: %s, line: %d\n",
            szExpr, szFile, nLine);
    DebugBreak();
}
#define assert(expr) \
    ((void)((expr) || (_DrvAssert(#expr, __FILE__, __LINE__), FALSE)))

#else

#define DBGOUT(m, x)
#define DBGOUT_FUNC(m, x)

#endif

////////////////////////////////////////////////////////////////////////////////
//
// Basic hardware macro
//
#define AUDIO_BUFSIZE 0x1000
#define AUDIO_BUFCNT  8

#define MAX_WAIT_TIME 800 // Max time (tick) to wait for recording,tick=10 ms

// Definitions for DMA control
#define DMA_MAP_VALID_MASK  (0x1U << 7)  // Request is mapped to a valid channel indicated by DRCMRx(3:0)

#define DCSR_BUSERRINTR     (0x1U << 0)  // Bus error status bit
#define DCSR_STARTINTR      (0x1U << 1)  // Descriptor fetch status
#define DCSR_ENDINTR        (0x1U << 2)  // finish status
#define DCSR_STOPINTR       (0x1U << 3)  // stopped status
#define DCSR_REQPEND        (0x1U << 8)  // Request Pending (read-only)
#define DCSR_STARTIRQEN     (0x1U << 21) // Enable the start interrupt (when the descriptor is loaded)
#define DCSR_EORSTOPEN      (0x1U << 26) //
#define DCSR_STOPIRQEN      (0x1U << 29) // Enable the stopped interrupt (when the descriptor is done)
#define DCSR_NOFETCH        (0x1U << 30) // Descriptor fetch mode, 0 = fetch
#define DCSR_RUN            (0x1U << 31) // run, 1=start

#define IRQ_DMAC 25

#define BITS_8_TO_16(x)      ((UInt16)(((Int32) ((UInt8) (x) - 128) ) << 8))
#define BITS_16_TO_8(x)      ((Byte) (((x) >> 8) + 128))

////////////////////////////////////////////////////////////////////////////////
//
// Audiocard State
//
#if 0
// Audiocard State definition in elaaudio.h
// Here it is a copy
//
// A 32 bits integer represents the state of a audiocard
//  Bit31: Power
//  Bit30-Bit24: Call State
//  Bit23-Bit20: Right channel source of audio in
//  Bit19-Bit16: Left channel source of audio in
//  Bit15-Bit8: Audio out device
//  Bit7-Bit0: Basic State
//
// 1. Basic state. Bit0-Bit7
//    When audiocard is used, must have at least one of them.
//    All are mutually exclusive expect STATE_AUDIOIN and CALL_HANDFREE
#define STATE_AUDIOOUT          0x00000001
#define STATE_AUDIOIN           0x00000002
#define STATE_CALL              0x00000004
// 2. Audio out device. Bit8-Bit15
#define AUDIOOUT_SPEAKER        0x00000100
#define AUDIOOUT_HEADSET        0x00000200
#define AUDIOOUT_BLUETOOTH      0x00000400
// 3. Audio in device
// Bit16-Bit19:  Left channel
// Bit20-Bit23:  Right channel
#define AUDIOIN_MAINMIC      0  // MIC on phone
#define AUDIOIN_HEADSET      1  // MIC on normal headset
#define AUDIOIN_BLUETOOTH    2  // MIC on wireless headset(such as bluetooth)
#define AUDIOIN_LINE1        3  // Line 1 input (Normal mode Rx voice signal)
#define AUDIOIN_LINE2        4  // Line 2 input (Headset mode Rx voice signal)
#define AUDIOIN_SOURCEMASK   0xf
#define AUDIOIN_SETLEFTSOURCE(source)  (((source) & 0xf) << 16)
#define AUDIOIN_SETRIGHTSOURCE(source) (((source) & 0xf) << 20)
#define AUDIOIN_GETLEFTSOURCE(state)  (UInt32)(((state) & 0x000f0000) >> 16)
#define AUDIOIN_GETRIGHTSOURCE(state) (UInt32)(((state) & 0x00f00000) >> 20)
// 4. Call State. Bit24-Bit30
#define CALL_NORMAL             0
#define CALL_HANDFREE           1
#define CALL_HEADSET            2
#define CALL_BLUETOOTH          3
#define CALL_MODEMASK           0x7f
#define CALL_SETMODE(call)   (((call) & 0xf) << 24)
#define CALL_GETMODE(state)  (UInt32)(((state) & 0x7f000000) >> 24)
// 5. Power state. Bit31
#define POWER_CLOSE             0x80000000 // Only for playing and recording
#endif

#ifdef BLUETOOTH_PLAY_RECORD_ENABLE
#define USING_BLUETOOTH(state) \
           ((CALL_BLUETOOTH == CALL_GETMODE(state))  || \
            (AUDIOIN_BLUETOOTH == AUDIOIN_GETLEFTSOURCE(state)) || \
            (AUDIOIN_BLUETOOTH == AUDIOIN_GETRIGHTSOURCE(state)))
#else
#define USING_BLUETOOTH(state) (CALL_BLUETOOTH == CALL_GETMODE(state))
#endif

#define AUDIOCARD_NOTPREPARED(state) ((state & 0x000000f) == 0)
////////////////////////////////////////////////////////////////////////////////
//
// Audiocard Aux State
//
#define AUXSTATE_HEADSETPLUG            0x00000001
#define AUXSTATE_HEADSETPLUGISR         0x00000002
#define AUXSTATE_SPEAKER_WORKING        0x00000010
#define AUXSTATE_HEADSETOUT_WORKING     0x00000020
#define AUXSTATE_BLUETOOTHOUT_WORKING   0x00000040
#define AUXSTATE_ACLINK_AUDIO           0x00000100
#define AUXSTATE_ACLINK_TOUCH           0x00000200
#define AUXSTATE_AMPLIFIER_OPEN         0x00001000
////////////////////////////////////////////////////////////////////////////////
//
// Status for special state control
//
// Audio buffer status
#define BUFSTATUS_INITIAL   0
#define BUFSTATUS_NORMAL    1
#define BUFSTATUS_FULL      2
#define BUFSTATUS_EMPTY     3

// Audio out device
#define AODEVICE_SPEAKER    0
#define AODEVICE_HEADSET    1
#define AODEVICE_BTHEADSET  2

// Audio in channels
#define AICHANNEL_LEFT          0
#define AICHANNEL_RIGHT         1
#define AICHANNEL_CLOSE         2

// volume type
#define VOLUMETYPE_SPEAKER      0
#define VOLUMETYPE_HEADSET      1
#define VOLUMETYPE_MONO         2
#define VOLUMETYPE_MIC          3
#define VOLUMETYPE_DACGAIN      4
#define VOLUMETYPE_BTHEADSET    5

////////////////////////////////////////////////////////////////////////////////
//
// Audio context
//
typedef struct {
        UInt32 state; // See Audiocard State Flags
        UInt32 auxState; // See Audiocard State Flags
        DzMutex acLinkLock;

        // STATE_AUDIOOUT
        Audio_Params aoParams;
        UInt32 aoFillingBufIdx;
        UInt32 aoTransBufIdx;
        UInt32 aoBufCnt;
        UInt32 aoBufStatus; // See UInt32
        Byte aoVolLeft;
        Byte aoVolRight;
        Int16 aoReserved;
        int aoDmaCh;
        void (*aoBufCopyFunc)(Byte *pDes, Byte *pSrc, UInt32 cnt);
        Boolean aoDmaInProgess;
        Address aoBufferVirtAddr;
        Address aoBufferPhysAddr;
        Address aoDmaDescVirtAddr;
        Address aoDmaDescPhysAddr;

        // STATE_AUDIOIN
        Audio_Params aiParams;
        UInt32 aiGettingBufPos;
        UInt32 aiGettingBufIdx;
        UInt32 aiTransBufIdx;
        UInt32 aiBufCnt;
        UInt32 aiBufStatus; // See UInt32
        Byte aiVolLeft; // Reserved
        Byte aiVolRight; // Reserved
        Int16 aiReserved;
        int aiDmaCh;
        void (*aiBufCopyFunc)(Byte *pDes, Byte *pSrc, UInt32 cnt);
        Boolean aiDmaInProgess;
        Address aiBufferVirtAddr;
        Address aiBufferPhysAddr;
        Address aiDmaDescVirtAddr;
        Address aiDmaDescPhysAddr;

        // STATE_CALL
        Byte callVolume;
} AudioContext;

////////////////////////////////////////////////////////////////////////////////
//
// Functions
//
ECode Audio_Create(AudioContext *pCxt);
ECode Audio_GetState(AudioContext *pCxt, Audio_Status *pStatus);
ECode Audio_InitHardware(AudioContext *pCxt);

ECode AO_OpenHardware(AudioContext *pCxt);
ECode AO_Open(AudioContext *pCxt, Audio_Params *pParams);
void AO_CloseHardware(AudioContext *pCxt);
void AO_Close(AudioContext *pCxt);
void AO_Reset(AudioContext *pCxt);
ECode AO_SetVolume(AudioContext *pCxt, Byte left, Byte right);
void AO_GetVolume(AudioContext *pCxt, Byte *pLeft, Byte *pRight);
ECode AO_FlushBuffer(AudioContext *pCxt);
ECode AO_Write( AudioContext *pCxt,
        void *pData, UInt32 dataLen, UInt32 * pWritten);
Boolean AO_DmaIsr(AudioContext *pCxt, PBoolean pWakeUp);
ECode AO_SelectDevice(AudioContext *pCxt, UInt32 device);
ECode AO_CloseDevice(AudioContext *pCxt, UInt32 device);

ECode AI_OpenHardware(AudioContext *pCxt);
ECode AI_Open(AudioContext *pCxt, Audio_Params *pParams);
void AI_CloseHardware(AudioContext *pCxt);
void AI_Close(AudioContext *pCxt);
void AI_Reset(AudioContext *pCxt);
ECode AI_SetVolume(AudioContext *pCxt, Byte left, Byte right);
void AI_GetVolume(AudioContext *pCxt, Byte *pLeft, Byte *pRight);
ECode AI_Read( AudioContext *pCxt,
        void *pData, UInt32 dataLen, UInt32 * pRead);
Boolean AI_DmaIsr(AudioContext *pCxt, PBoolean pWakeUp);
ECode AI_SelectSource(AudioContext *pCxt,  Byte left, Byte right);

ECode Call_Open(AudioContext *pCxt, UInt32 callMode);
void Call_Close(AudioContext *pCxt);
ECode Call_SetVolume(AudioContext *pCxt, Byte volume);

void Power_Open(AudioContext *pCxt);
void Power_Close(AudioContext *pCxt);

ECode Codec_OpenAc97DAC(AudioContext *pCxt);
ECode Codec_OpenAc97ADC(AudioContext *pCxt);
ECode Codec_SetAudioInSource(AudioContext *pCxt, UInt32 channel, Byte source);
ECode Codec_OpenNormalCall(AudioContext *pCxt);
void Codec_CloseNormalCall(AudioContext *pCxt);
ECode Codec_OpenHandFreeCall(AudioContext *pCxt);
void Codec_CloseHandFreeCall(AudioContext *pCxt);
ECode Codec_OpenBluetoothCall(AudioContext *pCxt);
void Codec_CloseBluetoothCall(AudioContext *pCxt);
ECode Codec_OpenHeadsetCall(AudioContext *pCxt);
void Codec_CloseHeadsetCall(AudioContext *pCxt);
void Codec_SetGpios(AudioContext *pCxt);
ECode Codec_Init(AudioContext *pCxt);
void Codec_Close(AudioContext *pCxt);
ECode Codec_SetSampleRate(UInt32 rate, UInt32 dir);
ECode Codec_SetVolume(AudioContext *pCxt, Byte left, Byte right, UInt32 volType);
void Codec_OpenAmplifier(AudioContext *pCxt, Boolean bOpen);
void Codec_GetHeadsetStatus(AudioContext *pCxt);
ECode Codec_InitHeadset(AudioContext *pCxt);
ECode Codec_SetRecordVolume(AudioContext *pCxt, Byte left, Byte right);
ECode Codec_SetCallVolume(AudioContext *pCxt, Byte volume);

ECode Ac97_Read(UInt8 Offset, UInt16 * Data);
ECode Ac97_Write(UInt8 Offset, UInt16  Data);
void Ac97_Reset(AudioContext *pCxt);
void Ac97_WarmReset(AudioContext *pCxt, UInt32 flag);
void Ac97_Close(AudioContext *pCxt, UInt32 flag);

#if (_TEST_TYPE == 41)      /* Test for Runtime of ISR */
void SetOutIsrTime(/* [out] */ MemoryBuf * pOutData);
void SetRcvIsrTime(/* [out] */ MemoryBuf * pOutData);
#endif //_TEST_TYPE == 41

#endif//__AUDIOCARD_H__
